using System;
using System.Collections.Generic;
using Framework;
using UnityEngine;
public class PlayerInput
{
    private static bool _inited;
    public PlayerInput()
    {
        var inputControls = new GameInputControls();
        inputControls.Enable();
        init(inputControls.asset);
    }
    private void init(UnityEngine.InputSystem.InputActionAsset inputActionAsset)
    {
        if (_inited)
        {
            return;
        }
        _inited = true;
        Dictionary<string, bool> _actions = new Dictionary<string, bool>();
        foreach (var item in inputActionAsset.bindings)
        {
            if (!_actions.TryGetValue(item.action, out var exist))
            {
                var action = inputActionAsset.FindAction(item.action, true);
                action.started += onActionStarted;
                action.performed += onActionPerformed;
                action.canceled += onActionCanceled;
            }
        }
        UnityEngine.InputSystem.InputSystem.onDeviceChange += OnInputDeviceChanged;
        updateDevice();
    }
    private void OnInputDeviceChanged(UnityEngine.InputSystem.InputDevice device, UnityEngine.InputSystem.InputDeviceChange change)
    {
        updateDevice();
    }
    private void updateDevice()
    {
        GameEntry.DeviceManager.ClearDevice();
        var devices = UnityEngine.InputSystem.InputSystem.devices;
        foreach (var item in devices)
        {
            var mdevice = GameEntry.DeviceManager.AddDevice(item.deviceId, item.name);
        }
    }
    private void onActionStarted(UnityEngine.InputSystem.InputAction.CallbackContext obj)
    {
        var device = GameEntry.DeviceManager.GetDevice(obj.control.device.deviceId);
        if (device == null) return;
        if (obj.valueType == typeof(Vector2))
        {
            var v2 = obj.ReadValue<Vector2>();
            device.SetValue(obj.action.name, v2.x, v2.y);
        }
        else
        {
            device.SetValue(obj.action.name, obj.ReadValue<float>());
        }
        device.Start(obj.action.name, GetInteractionType(obj.interaction));
    }
    private void onActionPerformed(UnityEngine.InputSystem.InputAction.CallbackContext obj)
    {
        var device = GameEntry.DeviceManager.GetDevice(obj.control.device.deviceId);
        if (device == null) return;
        if (obj.valueType == typeof(Vector2))
        {
            var v2 = obj.ReadValue<Vector2>();
            device.SetValue(obj.action.name, v2.x, v2.y);
        }
        else
        {
            device.SetValue(obj.action.name, obj.ReadValue<float>());
        }
        device.Perform(obj.action.name, GetInteractionType(obj.interaction));
    }
    private void onActionCanceled(UnityEngine.InputSystem.InputAction.CallbackContext obj)
    {
        var device = GameEntry.DeviceManager.GetDevice(obj.control.device.deviceId);
        if (device == null) return;
        device.Cancel(obj.action.name, GetInteractionType(obj.interaction));
    }
    private InteractionType GetInteractionType(UnityEngine.InputSystem.IInputInteraction value)
    {
        if (value == null)
        {
            return InteractionType.None;
        }
        if (value is UnityEngine.InputSystem.Interactions.TapInteraction)
        {
            return InteractionType.Tap;
        }
        else if (value is UnityEngine.InputSystem.Interactions.HoldInteraction)
        {
            return InteractionType.Hold;
        }
        else if (value is UnityEngine.InputSystem.Interactions.SlowTapInteraction)
        {
            return InteractionType.SlowTap;
        }
        else if (value is UnityEngine.InputSystem.Interactions.MultiTapInteraction)
        {
            return InteractionType.MultiTap;
        }
        else if (value is UnityEngine.InputSystem.Interactions.PressInteraction press)
        {
            if (press.behavior == UnityEngine.InputSystem.Interactions.PressBehavior.PressOnly)
            {
                return InteractionType.Press;
            }
            else if (press.behavior == UnityEngine.InputSystem.Interactions.PressBehavior.ReleaseOnly)
            {
                return InteractionType.Release;
            }
            else
            {
                return InteractionType.PressAndRelease;
            }
        }
        return InteractionType.None;
    }
}